home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 34.zip / BS1 part 34 / FredFish PD 305.adf / Mackie / mackie.c < prev    next >
C/C++ Source or Header  |  1990-01-17  |  49KB  |  1,880 lines

  1. /*
  2.     Modified to work with Manx 3.6a; probably won't work with Lattice.
  3.                                 Based on:
  4.                                                                              */
  5. /*  Compile with -DSPLINES for splines instead of lines                      */
  6. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  7. /* |_o_o|\\ Copyright (c) 1986 The Software Distillery.  All Rights Reserved */
  8. /* |. o.| || This program may not be distributed without the permission of   */
  9. /* | .  | || the authors.                                                    */
  10. /* | o  | ||    Dave Baker     Ed Burnette  Stan Chow    Jay Denebeim        */
  11. /* |  . |//     Gordon Keener  Jack Rouse   John Toebes  Doug Walker         */
  12. /* ======          BBS:(919)-471-6436      VOICE:(919)-469-4210              */ 
  13. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  14. /*
  15.  * VERY loosely based on the input.device example by Rob Peck, 12/1/85
  16.  */
  17. /* * * * * * * * * INCLUDE FILES * * * * * * * * * * * */
  18. #include <exec/types.h>
  19. #include <exec/nodes.h>
  20. #include <exec/lists.h>
  21. #include <exec/memory.h>
  22. #include <exec/interrupts.h>
  23. #include <exec/ports.h>
  24. #include <exec/libraries.h>
  25. #include <exec/io.h>
  26. #include <exec/tasks.h>
  27. #include <exec/execbase.h>
  28. #include <exec/devices.h>
  29. #include <devices/timer.h>
  30. #include <devices/input.h>
  31. #include <devices/inputevent.h>
  32. #include <devices/console.h>
  33. #include <intuition/intuition.h>
  34. #include <intuition/intuitionbase.h>
  35. #include <libraries/dos.h>
  36. #include <libraries/dosextens.h>
  37. #include <graphics/gfxmacros.h>
  38. #include <hardware/custom.h>
  39. #include <hardware/dmabits.h>
  40. /*
  41.  *   I need this kludge because of a bug in functions.h.
  42.  */
  43. #define ConsoleDevice IDontReallyExist
  44. #include <functions.h>
  45. #undef ConsoleDevice
  46. #include <stdio.h>
  47.  
  48. /* * * * * * * * * * * CONSTANTS * * * * * * * * * * * * */
  49. #define PORTNAME     "Mackie.port"
  50. #define TIMEINTERVAL 1L      /* in seconds */
  51. #define DEFTIME      300     /* two minute timeout */
  52. #define MAXCMD       200
  53. #define MAXPENDINGSYSTEM 20
  54. #define DEFKEY    0x45
  55. #define DEFCMD    "NEWCLI >NIL: <NIL:"
  56. #define STARTUPFILE "s:.mackierc"
  57. /*
  58.  *   Macro to make BPTR things easier to work with.
  59.  */
  60. #define BSTRtoS(a) ((char *)(((long)(a))<<2))
  61. /* * * * * * * * * * * GLOBAL VARIABLES * * * * * * * * * */
  62. /*
  63.  *   Detach stuff (doesn't work, somehow!)
  64.  */
  65. struct Task          *globalbuddy ;
  66. ULONG                 globalcreatclisig ;
  67. ULONG                 globalunblanksig ;
  68. ULONG                 globalfrontsig ;
  69. ULONG                 globalnoevents ;
  70. short                 globalcreatsignum ;
  71. short                 globalblanksignum ;
  72. short                 globalreplysignum ;
  73. short                 globalfrontsignum ;
  74. short                 globalkey ;
  75. char                  globalfrontkey[MAXPENDINGSYSTEM] ;
  76. char                  globalfrontqual[MAXPENDINGSYSTEM] ;
  77. short                 globalfrontptr ;
  78. short                 globaldraw ;
  79. short                 globalhelppressed ;
  80. struct Screen        *globalblankscreen ;
  81. #define SHIFT 1
  82. #define NOTCLI 2
  83. #define NOTINTUITION 4
  84. struct hotkey {
  85.    struct hotkey*next ;
  86.    char key, flags ;
  87.    int structlen ;
  88.    char *matchstring, *startstring ;
  89.    char strings[2] ;
  90. } *hotkeys ;
  91. struct Window *lastwindows[200] ;
  92. struct Task *task ;
  93. long taskreply ; /* the signal the line drawing task will return */
  94. #define STACKSIZE (1000)
  95. long stackmem[STACKSIZE/4] ;
  96. struct InfoData *infoptr ;
  97. struct MsgPort *FindPort(), *CreatePort();
  98. void DeletePort();
  99. char *startupfile = STARTUPFILE ;
  100. struct OURMSG {
  101.  struct Message msgpart;
  102.  short key;
  103.  short interval;
  104.  short draw ;
  105.  char cmd[MAXCMD];
  106.  };
  107. short oldtime ;
  108. extern char *strcpy() ;
  109.  
  110. /************************************************************************/
  111. /* the handler subroutine - called through the handler stub             */
  112. /************************************************************************/
  113. extern void HandlerInterface();
  114. void foobar() {
  115. #asm
  116. _HandlerInterface:
  117.     movem.l a4,-(a7)
  118.     movem.L    A0/A1,-(A7)
  119.     jsr    _geta4#
  120.     jsr    _myhandler
  121.     addq.L    #8,A7
  122.     movem.L    (a7)+,a4
  123.     rts
  124. #endasm
  125. }
  126. char keytoasc[128] ;
  127. struct InputEvent *myhandler(ev, gptr)
  128. struct InputEvent *ev;      /* and a pointer to a list of events */
  129. long gptr ; /* ignore */
  130. {
  131.    register struct InputEvent *ep, *laste;
  132.    int key ;
  133.    /*
  134.     * run down the list of events
  135.     * to see if they pressed
  136.     * one of the magic buttons
  137.     */
  138.    for (ep = ev, laste = NULL; ep != NULL; ep = ep->ie_NextEvent) {
  139.       if ((ep->ie_Class == IECLASS_RAWKEY)    &&
  140.              (((ep->ie_Qualifier & IEQUALIFIER_LCOMMAND) &&
  141.                (ep->ie_Code == globalkey))
  142. #ifdef HELPKEY
  143.            || (!globalhelppressed && ep->ie_Code == 0x5f) ||
  144.               (globalhelppressed &&
  145.                (ep->ie_Code & 0x80) == 0 &&
  146. /*
  147.  *   All the qualifiers have code = 0x6?; dangerous to take advantage
  148.  *   of?
  149.  */
  150.                (ep->ie_Code & 0xf0) != 0x60 &&
  151.                globalfrontkey[globalfrontptr] == 0 &&
  152.                (globalhelppressed = (keytoasc[ep->ie_Code] != '.')))
  153. #endif
  154.             )) {
  155.          if ((ep->ie_Qualifier & IEQUALIFIER_LCOMMAND) &&
  156.               (ep->ie_Code == globalkey)) {
  157.             key = -1 ;
  158. #ifdef HELPKEY
  159.          } else if (globalhelppressed) {
  160.             globalfrontkey[globalfrontptr] = key = ep->ie_Code ;
  161.             globalfrontqual[globalfrontptr] = ep->ie_Qualifier ;
  162.             globalfrontptr++ ;
  163.             if (globalfrontptr >= MAXPENDINGSYSTEM)
  164.                globalfrontptr = 0 ;
  165.             globalhelppressed = 0 ;
  166.          } else {
  167.             globalhelppressed = 1 ;
  168.             key = 0 ;
  169. #endif
  170.          }
  171.          /* we can handle this event so take it off the chain */
  172.          if (laste == NULL)
  173.             ev = ep->ie_NextEvent;
  174.          else
  175.             laste->ie_NextEvent = ep->ie_NextEvent;
  176.          /* now tell him to create the new cli */
  177.          if (key == -1)
  178.             Signal(globalbuddy, globalcreatclisig);
  179. #ifdef HELPKEY
  180.          else if (key > 0)
  181.             Signal(globalbuddy, globalfrontsig);
  182. #endif
  183.       } else
  184.          laste = ep;
  185.       if (ep->ie_Class != IECLASS_TIMER) {
  186.          globalnoevents = 0;
  187.          if (globalblankscreen != NULL)
  188.             Signal(globalbuddy, globalunblanksig);
  189.       }
  190.    }
  191.    /* pass on the pointer to the event */
  192.    return(ev);
  193. }
  194.  
  195. /* * * * * * * * * * * EXTERNAL ROUTINES * * * * * * * * * */
  196. struct IntuitionBase *IntuitionBase;
  197. struct GfxBase       *GfxBase;
  198. struct DosLibrary    *DosBase;
  199. struct NewScreen      NewScreen = 
  200.    { 0, 0, 320, 30, 1, 0, 1, NULL, CUSTOMSCREEN, NULL, NULL, NULL, NULL };
  201.  
  202. extern struct MsgPort  *CreatePort();
  203. struct IOStdReq *CreateIOReq();
  204. void DeleteIOReq();
  205.  
  206. /************************************************************************/
  207. /* Queue a timer to go off in a given number of seconds                 */
  208. /************************************************************************/
  209. void QueueTimer(tr,seconds)
  210. register struct timerequest *tr;
  211. ULONG seconds;
  212. {
  213.    tr->tr_node.io_Command = TR_ADDREQUEST;   /* add a new timer request */
  214.    tr->tr_time.tv_secs =  seconds;            /* seconds */
  215.    tr->tr_time.tv_micro = 0;
  216.    SendIO( (struct IORequest *)tr );
  217. }
  218. /*
  219.  *   A utility to change our priority.
  220.  */
  221. prito(n)
  222. int n ;
  223. {
  224.    SetTaskPri(FindTask(0L), (long)n) ;
  225. }
  226. /************************************************************************/
  227. /* the main program to do the popcli stuff                              */
  228. /************************************************************************/
  229. main(argc, argv)
  230. int argc ;
  231. char *argv[] ;
  232. {
  233.    struct MsgPort *port;
  234.    int stay = 0;
  235.    register struct OURMSG *msg;
  236.    int i ;
  237.    char cmdstr[MAXCMD];
  238.    short key, timeout ;
  239.    struct FileHandle *nullfh = NULL ;
  240.    ULONG sig, timersig;
  241.    struct timerequest *timerreq;
  242.    struct MsgPort     *timerport;
  243.    struct MsgPort     *inputDevPort;
  244.    struct IOStdReq    *inputRequestBlock;
  245.    register struct Interrupt handlerStuff;
  246.    char *cmd ;
  247.    int draw = 0 ;
  248.    int nextfront = 0 ;
  249.  
  250.    prito(20) ;
  251.    globalcreatsignum  = -1;
  252.    globalblanksignum  = -1;
  253.    globalreplysignum  = -1;
  254.    globalfrontsignum  = -1;
  255.    globalblankscreen  = NULL;
  256.    globalkey          = DEFKEY ;
  257.    globaldraw         = 1 ;
  258.    timerreq            = NULL;
  259.    timerport           = NULL;
  260.    inputDevPort        = NULL;
  261.    inputRequestBlock   = NULL;
  262.    /* now see if we are already installed */
  263.    if ((port = FindPort(PORTNAME)) == NULL) {
  264.       stay = 1; /* remember to hang around when we are done */
  265.       /* not installed, we need to install our own port */
  266.       if ((port = CreatePort(PORTNAME,0L)) == NULL)
  267.          goto abort;
  268.    }
  269. #ifdef HELPKEY
  270. /*
  271.  *   If we are hanging around, initialize our keyboard translation table.
  272.  *   If we have difficulty, exit angry.
  273.  */
  274.    if (stay)
  275.       if (initkeytoasc())
  276.          goto abort ;
  277. #endif
  278.    /* now send the parameter to the waiting program */
  279.    if ((msg = (struct OURMSG *)
  280.        AllocMem((long)sizeof(struct OURMSG), MEMF_CLEAR|MEMF_PUBLIC)) == NULL)
  281.       goto abort;
  282.    if ((infoptr = (struct InfoData *)
  283.       AllocMem((long)sizeof(struct InfoData), MEMF_CLEAR)) == NULL)
  284.       goto abort ;
  285.    /* fill in the message information */
  286.    msg->msgpart.mn_Length = sizeof(struct OURMSG);
  287.    strcpy(cmdstr, DEFCMD);
  288.    timeout = -1 ;
  289.    key = 0 ;
  290.    msg->cmd[0] = 0;
  291.    /* if we were run from CLI then output our banner and process parameters */
  292.    if (argc > 0) {
  293.       /* display our copyright */
  294.       if (stay)
  295.          puts("Mackie 1.4 by Tomas Rokicki - Copyright \xa9 1987-9 Radical Eye Software") ;
  296.       if (argc == 1)
  297.          puts("Usage: Mackie [-q] [-l] [-b] [-f startup] [time] [\"command\"]") ;
  298.       argc-- ;
  299.       argv++ ;
  300.       while (argc > 0) {
  301.          cmd = argv[0] ;
  302.          if (*cmd == '-') {
  303.             cmd++ ;
  304.             switch (*cmd) {
  305. case 'q' : case 'Q' :
  306.                key = -1 ;
  307.                puts("\x9B1mMackie\x9B0m Terminating") ;
  308.                break ;
  309. case 'l' : case 'L' :
  310.                draw = 1 ;
  311.                break ;
  312. case 'b' : case 'B' :
  313.                draw = -1 ;
  314.                break ;
  315. case 'f' : case 'F' :
  316.                if (cmd[1])
  317.                   startupfile = cmd + 1 ;
  318.                else {
  319.                   argv++ ;
  320.                   argc-- ;
  321.                   startupfile = argv[0] ;
  322.                }
  323.                break ;
  324. default :
  325.                puts("Error in parameter!") ;
  326.             }
  327.          } else if ('0' <= *cmd && *cmd <= '9') {
  328.             timeout = 0;
  329.             while ((*cmd >= '0') && (*cmd <= '9'))
  330.                timeout = (timeout*10) + *cmd++ - '0';
  331.             if (timeout < 0)
  332.                timeout = DEFTIME;
  333.          } else {
  334.             strcpy(msg->cmd, cmd) ;
  335.          }
  336.          argc-- ;
  337.          argv++ ;
  338.       }
  339.    }
  340.    msg->interval = timeout;
  341.    msg->key = key;
  342.    msg->draw = draw ;
  343.    if (stay)
  344.       processstartup(startupfile, msg) ;
  345.    if (draw)
  346.       globaldraw = draw ;
  347.    PutMsg(port,(struct Message *)msg);
  348.    if (!stay) goto abort;
  349.    if (timeout == -1)
  350.       timeout = DEFTIME ;
  351.    globalblankscreen = NULL;
  352.    globalbuddy = FindTask(0L);
  353.    globalnoevents = 0;
  354.    nullfh = Open("NIL:", MODE_NEWFILE);
  355.    if (((inputDevPort = CreatePort(0L,0L)) == NULL) ||
  356.       ((inputRequestBlock =
  357.           CreateIOReq(inputDevPort, (long)sizeof(struct IOStdReq))) == NULL) ||
  358.       ((timerport = CreatePort(0L,0L)) == NULL) ||
  359.       ((timerreq  = (struct timerequest *)
  360.           CreateIOReq(timerport, (long)sizeof(struct timerequest))) == NULL))
  361.          goto abort ;
  362.    if (((globalcreatsignum = AllocSignal(-1L)) == -1) ||
  363.       ((globalblanksignum = AllocSignal(-1L)) == -1) ||
  364.       ((globalreplysignum = AllocSignal(-1L)) == -1) ||
  365.       ((globalfrontsignum = AllocSignal(-1L)) == -1) ||
  366.       ((GfxBase = (struct GfxBase *)
  367.                   OpenLibrary("graphics.library", 0L)) == NULL) ||
  368.       ((IntuitionBase = (struct IntuitionBase *)
  369.                         OpenLibrary("intuition.library", 0L)) == NULL) ||
  370.       OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)timerreq, 0L) ||
  371.       OpenDevice("input.device",0L,(struct IORequest *)inputRequestBlock,0L))
  372.          goto abort;
  373.    handlerStuff.is_Data = (APTR)0L ;
  374.    handlerStuff.is_Code = HandlerInterface;
  375.    handlerStuff.is_Node.ln_Pri = 51;
  376.    timersig            = (1L << timerport->mp_SigBit);
  377.    globalcreatclisig  = 1L << globalcreatsignum;
  378.    globalunblanksig   = 1L << globalblanksignum;
  379.    globalfrontsig     = 1L << globalfrontsignum;
  380.    inputRequestBlock->io_Command = IND_ADDHANDLER;
  381.    inputRequestBlock->io_Data    = (APTR)&handlerStuff;
  382.    DoIO((struct IORequest *)inputRequestBlock);
  383.    QueueTimer(timerreq, TIMEINTERVAL);
  384.    for(;;) {         /* FOREVER */
  385.       sig = Wait( globalcreatclisig | globalunblanksig | timersig |
  386.                   globalfrontsig);
  387.       /* see if they asked us to change the interval */
  388.       if ((msg = (struct OURMSG *)GetMsg(port)) != NULL) {
  389.          if (msg->cmd[0]) strcpy(cmdstr, msg->cmd);
  390.          if (msg->key)
  391.             globalkey = msg->key;
  392.          if (msg->interval != -1)
  393.             timeout    = msg->interval;
  394.          if (msg->draw)
  395.             globaldraw = msg->draw ;
  396.          FreeMem((char *)msg, (long)msg->msgpart.mn_Length);
  397.          if (msg->key == -1) goto abort;
  398.       }
  399.       if ((sig & globalunblanksig) && globalblankscreen)
  400.          screenunblank() ;
  401.       if (sig & globalcreatclisig) {
  402.          WBenchToFront();
  403.          prito(0) ;
  404.          (void)Execute(cmdstr,nullfh,nullfh);
  405.          prito(20) ;
  406.       }
  407. #ifdef HELPKEY
  408.       if (sig & globalfrontsig) {
  409.          while (i=globalfrontkey[nextfront]) {
  410.             windowtofront(keytoasc[i], globalfrontqual[nextfront]) ;
  411.             globalfrontkey[nextfront] = 0 ;
  412.             nextfront++ ;
  413.             if (nextfront >= MAXPENDINGSYSTEM)
  414.                nextfront = 0 ;
  415.          }
  416.       }
  417. #endif
  418.       if (sig & timersig) {
  419.          /* get rid of the message */
  420.          oldtime++ ;
  421.          (void)GetMsg(timerport);
  422.          QueueTimer(timerreq, TIMEINTERVAL);
  423.          if (task)
  424.             SetTaskPri(task, 10L) ;
  425.          if (timeout != 0 && (globalnoevents++ >= timeout) && (globalblankscreen == NULL))
  426.             blankscreen() ;
  427.       }
  428.    }
  429. abort:
  430.    if (infoptr) {
  431.       FreeMem(infoptr, (long)sizeof(struct InfoData)) ;
  432.       infoptr = NULL ;
  433.    }
  434.    if (timerreq != NULL) {
  435.       if (timerreq->tr_node.io_Device != NULL)
  436.          CloseDevice((struct IORequest *)timerreq);
  437.       DeleteIOReq((struct IOStdReq *)timerreq);
  438.    }
  439.    if (inputRequestBlock != NULL) {
  440.       if (inputRequestBlock->io_Device != NULL) {
  441.          inputRequestBlock->io_Command = IND_REMHANDLER;
  442.          inputRequestBlock->io_Data = (APTR)&handlerStuff;
  443.          DoIO((struct IORequest *)inputRequestBlock);
  444.          CloseDevice((struct IORequest *)inputRequestBlock);
  445.       }
  446.       DeleteIOReq(inputRequestBlock);
  447.    }
  448.    screenunblank() ;
  449.    if (timerport != NULL)          DeletePort(timerport);
  450.    if (globalcreatsignum != -1)   FreeSignal(globalcreatsignum);
  451.    if (globalblanksignum != -1)   FreeSignal(globalblanksignum);
  452.    if (globalreplysignum != -1)   FreeSignal(globalreplysignum);
  453.    if (globalfrontsignum != -1)   FreeSignal(globalfrontsignum);
  454.    if (IntuitionBase != NULL)      CloseLibrary((struct Library *)IntuitionBase);
  455.    if (GfxBase != NULL)            CloseLibrary((struct Library *)GfxBase);
  456.    if (inputDevPort != NULL)       DeletePort(inputDevPort);
  457.    if (stay && (port != NULL))     DeletePort(port);
  458.    {
  459.       struct hotkey *hk ;
  460.  
  461.       while (hotkeys) {
  462.          hk = hotkeys->next ;
  463.          FreeMem(hotkeys, (long)hotkeys->structlen) ;
  464.          hotkeys = hk ;
  465.       }
  466.    }
  467.    if (nullfh)                     Close(nullfh);
  468.    prito(0) ;
  469. }
  470.  
  471. struct IOStdReq *
  472. CreateIOReq(port, size)
  473. struct MsgPort *port;
  474. long size;
  475. {
  476.    register struct IOStdReq *ioReq;
  477.  
  478.    if ((ioReq = (struct IOStdReq *)
  479.                 AllocMem(size, MEMF_CLEAR | MEMF_PUBLIC)) != NULL) {
  480.       ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  481.       ioReq->io_Message.mn_Node.ln_Pri  = 0;
  482.       ioReq->io_Message.mn_Length       = size;
  483.       ioReq->io_Message.mn_ReplyPort    = port;
  484.    }
  485.    return(ioReq);
  486. }
  487.  
  488. void DeleteIOReq(ioReq)
  489. register struct IOStdReq *ioReq;
  490. {
  491.    ioReq->io_Message.mn_Node.ln_Type = 0xff;
  492.    ioReq->io_Device = (struct Device *) -1;
  493.    ioReq->io_Unit = (struct Unit *) -1;
  494.    FreeMem( (char *)ioReq, (long)ioReq->io_Message.mn_Length);
  495. }
  496. /*
  497.  *   All of this stuff down here was written by Tomas Rokicki.
  498.  *   (C) Copyright 1987, 1988, Radical Eye Software.
  499.  */
  500. #include "graphics/gfxbase.h"
  501. /*
  502.  *   The maximum number of lines on the screen at once.
  503.  */
  504. #define MAXLINES (30)
  505. #define MAXPOINTS (20)
  506. int maxpoints ;
  507. /*
  508.  *   The external variables we access.
  509.  */
  510. struct RastPort *rastport ;
  511. short screenheight, screenwidth ;
  512. /*
  513.  *   Some locals to this file.
  514.  */
  515. static struct NewScreen newscreen = {
  516.    0, 0,
  517.    640, 400,
  518.    1,
  519.    0, 1,
  520.    HIRES | LACE | SCREENQUIET,
  521.    CUSTOMSCREEN,
  522.    NULL,
  523.    NULL,
  524.    NULL,
  525.    NULL } ;
  526. /*
  527.  *   This routine opens a screen and fires off the task if apropriate.
  528.  */
  529. void taskrout() ;
  530. blankscreen() {
  531.    register struct Task *rtask ;
  532.  
  533.    screenheight = 2 * GfxBase->NormalDisplayRows ;
  534.    screenwidth = GfxBase->NormalDisplayColumns ;
  535.    newscreen.Height = screenheight ;
  536.    newscreen.Width = screenwidth ;
  537.    if (globaldraw == -1 || AvailMem(MEMF_CHIP) < 70000L ||
  538.              (globalblankscreen = OpenScreen(&newscreen)) == NULL) {
  539.       if ((globalblankscreen = OpenScreen(&NewScreen)) != NULL) {
  540.          SetRGB4(&(globalblankscreen->ViewPort), 0L, 0L, 0L, 0L);
  541.          OFF_DISPLAY ;
  542.       }
  543.    } else {
  544.       if (globalblankscreen == NULL &&
  545.           (globalblankscreen = OpenScreen(&newscreen))==NULL)
  546.          return ;
  547. /*
  548.  *   Turning off the sprites is a little bit tricky.  A simple OFF_SPRITE
  549.  *   will continue to display the data in the current sprite registers.
  550.  *   This happens most often with the cursor.  To fix, we simply clear out
  551.  *   the sprite control registers after turning the sprites off.  This
  552.  *   might break all of the sprites when the system comes back up . . .
  553.  */
  554.       OFF_SPRITE ;
  555.       custom.spr[0].ctl = 0 ;
  556.       custom.spr[1].ctl = 0 ;
  557.       custom.spr[2].ctl = 0 ;
  558.       custom.spr[3].ctl = 0 ;
  559.       custom.spr[4].ctl = 0 ;
  560.       custom.spr[5].ctl = 0 ;
  561.       custom.spr[6].ctl = 0 ;
  562.       custom.spr[7].ctl = 0 ;
  563.       SetRGB4(&(globalblankscreen->ViewPort), 0L, 0L, 0L, 0L) ;
  564.       rastport = &(globalblankscreen->RastPort) ;
  565.       SetAPen(rastport, 0L) ;
  566.       Forbid() ;
  567.       RectFill(rastport, 0L, 0L, (long)screenwidth-1, 30L) ;
  568.       Permit() ;
  569.       SetAPen(rastport, 1L) ;
  570.       rtask = (struct Task *)AllocMem((long)sizeof(struct Task),
  571.                 MEMF_CLEAR | MEMF_PUBLIC) ;
  572.       if (rtask != NULL) {
  573.          rtask->tc_Node.ln_Pri = 10 ;
  574.          rtask->tc_Node.ln_Type = NT_TASK ;
  575.          rtask->tc_Node.ln_Name = "ri.Lines" ;
  576.          rtask->tc_SPLower = (APTR)stackmem ;
  577.          rtask->tc_SPUpper = rtask->tc_SPReg =
  578.                       (APTR)(stackmem + STACKSIZE/4 - 8) ;
  579.          AddTask(rtask, taskrout, 0L) ;
  580.          task = rtask ;
  581.       }
  582.    }
  583. }
  584. /*
  585.  *   Unblank the screen.  We kill the task with the standard ^C kill signal.
  586.  */
  587. #ifdef STATS
  588. long linestat, splinestat ;
  589. #endif
  590. screenunblank() {
  591.    if (task != NULL) {
  592.       Signal(task, 1L << SIGBREAKB_CTRL_C) ;
  593.       SetTaskPri(task, 11L) ;
  594.       Wait(1L << globalreplysignum) ;
  595.       RemTask(task);
  596.       FreeMem(task, (long)sizeof(struct Task)) ;
  597.       task = NULL ;
  598.    }
  599.    if (globalblankscreen != NULL) {
  600.       CloseScreen(globalblankscreen);
  601.       globalblankscreen = NULL ;
  602.       ON_DISPLAY ;
  603.       ON_SPRITE ;
  604.    }
  605. #ifdef STATS
  606.    printf("%ld %ld\n", splinestat, linestat) ;
  607.    linestat = 0 ;
  608.    splinestat = 0 ;
  609. #endif
  610. }
  611. /*
  612.  *   This routine returns a random value from 0 to n-1.
  613.  */
  614. int randm(i)
  615. int i ;
  616. {
  617.    static long seed ;
  618.    register long rseed ;
  619.    register long rval ;
  620.  
  621.    rseed = seed ;
  622.    if (rseed == 0)
  623.       rseed = 323214521 + globalblankscreen->MouseX +
  624.               globalblankscreen->MouseY ;
  625.    rseed = rseed * 123213 + 121 ;
  626.    rval = (rseed >> 5) & 65535 ;
  627.    seed = rseed ;
  628.    return ((i * rval) >> 16) ;
  629. }
  630. /*
  631.  *   This routine sets x and y values to a random number.
  632.  */
  633. static long x, y ;
  634. randomxy() {
  635.    x = randm(screenwidth) ;
  636.    y = randm(screenheight) ;
  637. }
  638. /*
  639.  *   Main routines are always fun.
  640.  */
  641. struct box {
  642.    short x[MAXPOINTS], y[MAXPOINTS] ;
  643. } store[MAXLINES] ;
  644. #define FIX(x) (((long)(x)) << 7)
  645. #define FIXH(x) (((long)((*(x)+(x)[1])>>1)) << 7)
  646. #define UNFIX(x) ((x)>>7)
  647. struct box *ptr ;
  648. struct box *eptr ;
  649. int numlines ;
  650. int mdelta = -1 ;
  651. int maxlines = MAXLINES/2 ;
  652. short dx[MAXPOINTS], dy[MAXPOINTS] ;
  653. short ox[MAXPOINTS], oy[MAXPOINTS] ;
  654. short nx[MAXPOINTS], ny[MAXPOINTS] ;
  655. short dr, dg, db ;
  656. short or, og, ob ;
  657. short nr, ng, nb ;
  658. long oldx, oldy, oldwidth, oldptr ;
  659. int oldcol ;
  660. /*
  661.  *   Draws a spline!  Expects all arguments in registers.
  662.  */
  663. #asm
  664.     public    _Draw
  665.     cseg
  666. rspline
  667.     move.l    a0,d0
  668.     sub.l    d6,d0
  669.     move.l    d0,d3
  670.     bpl    save1
  671.     neg.l    d0
  672. save1
  673.     move.l    a1,d1
  674.     sub.l    d7,d1
  675.     move.l    d1,d4
  676.     bpl    save2
  677.     neg.l    d1
  678. save2
  679.     move.l    d0,d2
  680.     cmp.l    d0,d1
  681.     bmi    save3
  682.     lsr.l    #3,d2
  683.     bra    save9
  684. save3
  685.     lsr.l    #3,d1
  686. save9
  687.     add.l    d1,d2
  688.     asr.l    #3,d2
  689.     beq    check2
  690.     asr.l    #5,d3
  691.     asr.l    #5,d4
  692.     move.l    a2,d0
  693.     sub.l    a0,d0
  694.     move.l    a3,d1
  695.     sub.l    a1,d1
  696.     asr.l    #5,d0
  697.     asr.l    #5,d1
  698.     muls.w    d4,d0
  699.     muls.w    d3,d1
  700.     sub.l    d1,d0
  701.     bpl    save4
  702.     neg.l    d0
  703. save4
  704.     cmp.l    d0,d2
  705.     ble    pushem
  706.     move.l    a5,d0
  707.     sub.l    a0,d0
  708.     move.l    a6,d1
  709.     sub.l    a1,d1
  710.     asr.l    #5,d0
  711.     asr.l    #5,d1
  712.     muls.w    d4,d0
  713.     muls.w    d3,d1
  714.     sub.l    d1,d0
  715.     bpl    save5
  716.     neg.l    d0
  717. save5
  718.     cmp.l    d0,d2
  719.     ble    pushem
  720. makeline
  721. #endasm
  722. #ifdef STATS
  723. #asm
  724.     add.l    #1,_linestat
  725. #endasm
  726. #endif
  727. #asm
  728.     lsr.l    #7,d7
  729.     move.l    d7,d1
  730.     lsr.l    #7,d6
  731.     move.l    d6,d0
  732.     movem.l    d2-d5/a0-a1,-(sp)
  733.     move.l    _oldx,d2
  734.     move.l    _oldy,d3
  735.     move.l    d0,_oldx
  736.     move.l    d1,_oldy
  737.     move.l    _oldwidth,d4
  738.     move.l    _oldptr,a0
  739.     jsr    mdraw
  740.     movem.l    (sp)+,d2-d5/a0-a1
  741.     rts
  742. check2
  743.     move.l    a0,d0
  744.     sub.l    a2,d0
  745.     bpl    ch1
  746.     neg.l    d0
  747. ch1
  748.     move.l    a1,d1
  749.     sub.l    a3,d1
  750.     bpl    ch2
  751.     neg.l    d1
  752. ch2
  753.     add.l    d0,d1
  754.     asr.l    #3,d1
  755.     bne    pushem
  756.     move.l    a0,d0
  757.     sub.l    a5,d0
  758.     bpl    ch3
  759.     neg.l    d0
  760. ch3
  761.     move.l    a1,d1
  762.     sub.l    a6,d1
  763.     bpl    ch4
  764.     neg.l    d1
  765. ch4
  766.     add.l    d0,d1
  767.     asr.l    #3,d1
  768.     beq    makeline
  769. pushem
  770.     movem.l    d6/d7,-(sp)
  771.     move.l    a5,d0
  772.     add.l    d6,d0
  773.     asr.l    #1,d0
  774.     move.l    a6,d1
  775.     add.l    d7,d1
  776.     asr.l    #1,d1
  777.     movem.l    d0/d1,-(sp)
  778.     move.l    a2,d2
  779.     add.l    a5,d2
  780.     asr.l    #1,d2
  781.     move.l    a3,d3
  782.     add.l    a6,d3
  783.     asr.l    #1,d3
  784.     move.l    d0,d4
  785.     add.l    d2,d4
  786.     asr.l    #1,d4
  787.     move.l    d1,d5
  788.     add.l    d3,d5
  789.     asr.l    #1,d5
  790.     movem.l    d4/d5,-(sp)
  791.     move.l    a0,d6
  792.     add.l    a2,d6
  793.     asr.l    #1,d6
  794.     move.l    a1,d7
  795.     add.l    a3,d7
  796.     asr.l    #1,d7
  797.     move.l    d2,d0
  798.     add.l    d6,d0
  799.     asr.l    #1,d0
  800.     move.l    d3,d1
  801.     add.l    d7,d1
  802.     asr.l    #1,d1
  803.     move.l    d6,a2
  804.     move.l    d7,a3
  805.     move.l    d0,d6
  806.     add.l    d4,d6
  807.     asr.l    #1,d6
  808.     move.l    d1,d7
  809.     add.l    d5,d7
  810.     asr.l    #1,d7
  811.     movem.l    d6/d7,-(sp)
  812.     move.l    d0,a5
  813.     move.l    d1,a6
  814.     jsr    rspline
  815.     movem.l    (sp)+,a0/a1
  816.     movem.l    (sp)+,a2/a3/a5/a6
  817.     movem.l    (sp)+,d6/d7
  818.     bra    rspline
  819. ;
  820.     include 'exec/types.i'
  821.     include 'hardware/custom.i'
  822.     include 'hardware/blit.i'
  823.     include 'hardware/dmabits.i'
  824. ;
  825.     xref    _custom
  826. ;
  827. ;
  828. ;   Our entry point.
  829. ;
  830. mdraw:
  831.     move.l    #$dff000,a1    ; Manx requires this
  832.     sub.w    d0,d2        ; calculate dx
  833.     bmi    xneg        ; if negative, octant is one of [3,4,5,6]
  834.     sub.w    d1,d3        ; calculate dy   ''   is one of [1,2,7,8]
  835.     bmi    yneg        ; if negative, octant is one of [7,8]
  836.     cmp.w    d3,d2        ; cmp |dx|,|dy|  ''   is one of [1,2]
  837.     bmi    ygtx        ; if y>x, octant is 2
  838.     moveq.l    #OCTANT1+LINEMODE,d5    ; otherwise octant is 1
  839.     bra    lineagain    ; go to the common section
  840. ygtx:
  841.     exg    d2,d3        ; X must be greater than Y
  842.     moveq.l    #OCTANT2+LINEMODE,d5    ; we are in octant 2
  843.     bra    lineagain    ; and common again.
  844. yneg:
  845.     neg.w    d3        ; calculate abs(dy)
  846.     cmp.w    d3,d2        ; cmp |dx|,|dy|, octant is [7,8]
  847.     bmi    ynygtx        ; if y>x, octant is 7
  848.     moveq.l    #OCTANT8+LINEMODE,d5    ; otherwise octant is 8
  849.     bra    lineagain
  850. ynygtx:
  851.     exg    d2,d3        ; X must be greater than Y
  852.     moveq.l    #OCTANT7+LINEMODE,d5    ; we are in octant 7
  853.     bra    lineagain
  854. xneg:
  855.     neg.w    d2        ; dx was negative! octant is [3,4,5,6]
  856.     sub.w    d1,d3        ; we calculate dy
  857.     bmi    xyneg        ; if negative, octant is one of [5,6]
  858.     cmp.w    d3,d2        ; otherwise it's one of [3,4]
  859.     bmi    xnygtx        ; if y>x, octant is 3
  860.     moveq.l    #OCTANT4+LINEMODE,d5    ; otherwise it's 4
  861.     bra    lineagain
  862. xnygtx:
  863.     exg    d2,d3        ; X must be greater than Y
  864.     moveq.l    #OCTANT3+LINEMODE,d5    ; we are in octant 3
  865.     bra    lineagain
  866. waitmore:
  867.     nop
  868.     nop
  869.     btst    #DMAB_BLTDONE-8,dmaconr(a1)
  870.     beq    donewait
  871.     bra    waitmore
  872. xyneg:
  873.     neg.w    d3        ; y was negative, in one of [5,6]
  874.     cmp.w    d3,d2        ; is y>x?
  875.     bmi    xynygtx        ; if so, octant is 6
  876.     moveq.l    #OCTANT5+LINEMODE,d5    ; otherwise, octant is 5
  877.     bra    lineagain
  878. xynygtx:
  879.     exg    d2,d3        ; X must be greater than Y
  880.     moveq.l    #OCTANT6+LINEMODE,d5    ; we are in octant 6
  881. lineagain:
  882.     mulu.w    d4,d1        ; Calculate y1 * width
  883.     ror.l    #4,d0        ; move upper four bits into hi word
  884.     add.w    d0,d0        ; multiply by 2
  885.     add.l    d1,a0        ; ptr += (x1 >> 3)
  886.     add.w    d0,a0        ; ptr += y1 * width
  887.     swap    d0        ; get the four bits of x1
  888.     or.w    _oldcol,d0    ; or with USEA, USEC, USED, F=A~C+~AC
  889.     lsl.w    #2,d3        ; Y = 4 * Y
  890.     add.w    d2,d2        ; X = 2 * X
  891.     move.w    d2,d1        ; set up size word
  892.     lsl.w    #5,d1        ; shift five left
  893.     add.w    #$42,d1        ; and add 1 to height, 2 to width
  894.     btst    #DMAB_BLTDONE-8,dmaconr(a1)    ; safety check
  895. waitblit:
  896.     btst    #DMAB_BLTDONE-8,dmaconr(a1)    ; wait for blitter
  897.     bne    waitmore
  898. donewait:
  899.     move.w    d3,bltbmod(a1)    ; B mod = 4 * Y
  900.     sub.w    d2,d3
  901.     ext.l    d3
  902.     move.l    d3,bltapt(a1)    ; A ptr = 4 * Y - 2 * X
  903.     bpl    lineover    ; if negative,
  904.     or.w    #SIGNFLAG,d5    ; set sign bit in con1
  905. lineover:
  906.     move.w    d0,bltcon0(a1)    ; write control registers
  907.     move.w    d5,bltcon1(a1)
  908.     move.w    d4,bltcmod(a1)    ; C mod = bitplane width
  909.     move.w    d4,bltdmod(a1)    ; D mod = bitplane width
  910.     sub.w    d2,d3
  911.     move.w    d3,bltamod(a1)    ; A mod = 4 * Y - 4 * X
  912.     move.w    #$8000,bltadat(a1)    ; A data = 0x8000
  913.     moveq.l    #-1,d5        ; Set masks to all ones
  914.     move.l    d5,bltafwm(a1)    ; we can hit both masks at once
  915.     move.l    a0,bltcpt(a1)    ; Pointer to first pixel to set
  916.     move.l    a0,bltdpt(a1)
  917.     move.w    d1,bltsize(a1)    ; Start blit
  918.     rts            ; and return, blit still in progress.
  919. #endasm
  920. /*
  921.  *   Now our linkage to the spline routine.  Parameters are in 8(a5)...
  922.  */
  923. int drawspline(x1, y1, x2, y2, x3, y3, x4, y4)
  924. long x1, y1, x2, y2, x3, y3, x4, y4 ;
  925. {
  926. #ifdef STATS
  927.     splinestat++ ;
  928. #endif
  929. #asm
  930.     movem.l    saver,-(sp)
  931.     move.l    8(a5),a0
  932.     move.l    12(a5),a1
  933.     move.l    16(a5),a2
  934.     move.l    20(a5),a3
  935.     move.l    28(a5),a6
  936.     move.l    32(a5),d6
  937.     move.l    36(a5),d7
  938.     move.l    24(a5),a5
  939.     jsr    rspline
  940.     movem.l    (sp)+,saver
  941. saver    reg    d0-d7/a0-a6
  942. #endasm
  943. }
  944. int closed ;
  945. char *nextlegal[] = { "01458", "236", "01458", "236", "01458", "23", "01458",
  946.                       "", "0145" } ;
  947. int advval[] = { 3, 2, 3, 2, 1, 0, 1, 0, 1 } ;
  948. unsigned char realfunc[14] ;
  949. char namefunc[20] ;
  950. struct IntuiText itext = { 1, 0, JAM1, 0, 0, NULL, (UBYTE *)&namefunc } ;
  951. saytext()
  952. {
  953.    PrintIText(rastport, &itext, 10L, 14L) ;
  954. }
  955. makefunc() {
  956.    register int i ;
  957.    register int goallen ;
  958.    register int sofar = 0 ;
  959.    register unsigned char *p ;
  960.    register char *nextpossib ;
  961.  
  962.    closed = randm(4) ;
  963.    switch(closed) {
  964. case 3:
  965.       closed = 2 ;
  966. case 2:
  967.       goallen = 3 + randm(4) ;
  968.       break ;
  969. case 1:
  970.       goallen = 4 + randm(7) ;
  971.       break ;
  972. case 0:
  973.       goallen = 2 + randm(8) ;
  974.       break ;
  975.    }
  976.    while (1) {
  977.       if (closed == 0)
  978.          nextpossib = "0145" ;
  979.       else
  980.          nextpossib = "0123456" ;
  981.       sofar = 0 ;
  982.       p = realfunc ;
  983.       while (sofar < goallen) {
  984.          i = nextpossib[randm(strlen(nextpossib))] - '0' ;
  985.          *p++ = i ;
  986.          nextpossib = nextlegal[i] ;
  987.          sofar += advval[i] ;
  988.       }
  989.       if (sofar == goallen) {
  990.          if (closed == 0) {
  991.             if (nextpossib[0] == '0')
  992.                break ;
  993.          } else {
  994.             if (*nextpossib == '0' || realfunc[0] < 4 || *(p-1) < 4) {
  995.                if ((*nextpossib == '0') ?
  996.                       ((realfunc[0] & 2) != 0) : ((realfunc[0] & 2) == 0)) {
  997.                   if (realfunc[0] != 5) {
  998.                      realfunc[0] ^= 2 ;
  999.                      break ;
  1000.                   }
  1001.                } else {
  1002.                   break ;
  1003.                }
  1004.             }
  1005.          }
  1006.       }
  1007.    }
  1008.    *p = 100 ;
  1009.    maxpoints = goallen ;
  1010.    switch (closed) {
  1011. case 2:
  1012.       for (i=0; i<p-realfunc; i++)
  1013.          p[i] = realfunc[i] ;
  1014.       p[p-realfunc] = 100 ;
  1015.       break ;
  1016. case 1:
  1017.       break ;
  1018. case 0:
  1019.       maxpoints++ ;
  1020.       break ;
  1021.    }
  1022.    for (i=0, p=realfunc; *p < 100; p++, i++)
  1023.       namefunc[i] = *p + '0' ;
  1024.    namefunc[i++] = ' ' ;
  1025.    namefunc[i++] = '0' + closed ;
  1026.    namefunc[i++] = ' ' ;
  1027.    namefunc[i++] = '0' + maxpoints ;
  1028.    namefunc[i] = 0 ;
  1029. }
  1030. #define HALF(a) ((*(a)+(a)[1])>>1)
  1031. draw_s_f(xptr, yptr)
  1032. register short *xptr, *yptr ;
  1033. {
  1034.    oldx = HALF(xptr) ;
  1035.    oldy = HALF(yptr) ;
  1036.    OwnBlitter() ;
  1037.    drawspline(FIX(oldx), FIX(oldy), FIX(xptr[1]), FIX(yptr[1]),
  1038.               FIX(xptr[2]), FIX(yptr[2]), FIXH(xptr+2), FIXH(yptr+2)) ;
  1039.    DisownBlitter() ;
  1040. }
  1041. draw_sf(xptr, yptr)
  1042. register short *xptr, *yptr ;
  1043. {
  1044.    oldx = HALF(xptr) ;
  1045.    oldy = HALF(yptr) ;
  1046.    OwnBlitter() ;
  1047.    drawspline(FIX(oldx), FIX(oldy), FIX(xptr[1]), FIX(yptr[1]),
  1048.               FIX(xptr[2]), FIX(yptr[2]), FIX(xptr[3]), FIX(yptr[3])) ;
  1049.    DisownBlitter() ;
  1050. }
  1051. draws_f(xptr, yptr)
  1052. register short *xptr, *yptr ;
  1053. {
  1054.    oldx = *xptr ;
  1055.    oldy = *yptr ;
  1056.    OwnBlitter() ;
  1057.    drawspline(FIX(*xptr), FIX(*yptr), FIX(xptr[1]), FIX(yptr[1]),
  1058.               FIX(xptr[2]), FIX(yptr[2]), FIXH(xptr+2), FIXH(yptr+2)) ;
  1059.    DisownBlitter() ;
  1060. }
  1061. drawsf(xptr, yptr)
  1062. register short *xptr, *yptr ;
  1063. {
  1064.    oldx = *xptr ;
  1065.    oldy = *yptr ;
  1066.    OwnBlitter() ;
  1067.    drawspline(FIX(*xptr), FIX(*yptr), FIX(xptr[1]), FIX(yptr[1]),
  1068.               FIX(xptr[2]), FIX(yptr[2]), FIX(xptr[3]), FIX(yptr[3])) ;
  1069.    DisownBlitter() ;
  1070. }
  1071. draw_lf(xptr, yptr)
  1072. register short *xptr, *yptr ;
  1073. {
  1074.    Move(rastport, (long)HALF(xptr), (long)HALF(yptr)) ;
  1075.    xptr++ ;
  1076.    yptr++ ;
  1077.    Draw(rastport, (long)*xptr, (long)*yptr) ;
  1078. }
  1079. drawl_f(xptr, yptr)
  1080. register short *xptr, *yptr ;
  1081. {
  1082.    Move(rastport, (long)*xptr, (long)*yptr) ;
  1083.    Draw(rastport, (long)HALF(xptr), (long)HALF(yptr)) ;
  1084. }
  1085. drawlf(xptr, yptr)
  1086. register short *xptr, *yptr ;
  1087. {
  1088.    Move(rastport, (long)*xptr, (long)*yptr) ;
  1089.    xptr++ ;
  1090.    yptr++ ;
  1091.    Draw(rastport, (long)*xptr, (long)*yptr) ;
  1092. }
  1093. drawnlf() {}
  1094. int (*funcs[])() = { &drawsf, &draws_f, &draw_sf, &draw_s_f,
  1095.                      &drawlf, &drawl_f, &draw_lf, NULL, &drawnlf } ;
  1096. drawfunc(bptr)
  1097. register struct box *bptr ;
  1098. {
  1099.    register long i ;
  1100.    register short *x, *y ;
  1101.    register unsigned char *p ;
  1102.  
  1103. /* saytext() ; */
  1104.    oldwidth = rastport->BitMap->BytesPerRow ;
  1105.    oldptr = (long)rastport->BitMap->Planes[0] ;
  1106.    switch(closed) {
  1107. case 2:
  1108.       for (i=0, x=&(bptr->x[0]), y=&(bptr->y[0]); i<maxpoints; i++, x++, y++) {
  1109.          x[maxpoints] = screenwidth - 1 - *x ;
  1110.          y[maxpoints] = screenheight - 1 - *y ;
  1111.       }
  1112. setup:
  1113.       x[maxpoints] = bptr->x[0] ;
  1114.       y[maxpoints] = bptr->y[0] ;
  1115.       x++, y++ ;
  1116.       x[maxpoints] = bptr->x[1] ;
  1117.       y[maxpoints] = bptr->y[1] ;
  1118.       break ;
  1119. case 1:
  1120.       x = &(bptr->x[0]) ;
  1121.       y = &(bptr->y[0]) ;
  1122.       goto setup ;
  1123.    }
  1124.    p = realfunc ;
  1125.    x = &(bptr->x[0]) ;
  1126.    y = &(bptr->y[0]) ;
  1127.    while (*p < 20) {
  1128.       (funcs[*p])(x, y) ;
  1129.       i = advval[*p] ;
  1130.       x += i ;
  1131.       y += i ;
  1132.       p++ ;
  1133.    }
  1134. }
  1135. /*
  1136.  *   Initialize things for the first lines.
  1137.  */
  1138. startlines() {
  1139.    register int i ;
  1140.  
  1141.    ptr = store ;
  1142.    eptr = store ;
  1143.    numlines = 0 ;
  1144.    if (dx[0] == 0) {
  1145.       for (i=0; i<MAXPOINTS; i++) {
  1146.          ox[i] = randm(screenwidth) ;
  1147.      oy[i] = randm(screenheight) ;
  1148.      dx[i] = 2 + randm(3) ;
  1149.      dy[i] = 2 + randm(3) ;
  1150.       }
  1151.    }
  1152.    nr = 53 ;
  1153.    ng = 33 ;
  1154.    nb = 35 ;
  1155.    dr = -3 ;
  1156.    dg = 5 ;
  1157.    db = 7 ;
  1158.    SetRGB4(&(globalblankscreen->ViewPort), 0L, 0L, 0L, 0L) ;
  1159.    SetRGB4(&(globalblankscreen->ViewPort), 1L, (long)(nr >> 3),
  1160.                                  (long)(ng >> 3), (long)(nb >> 3)) ;
  1161.    for (i=0; i<maxlines; i++) {
  1162.       advancelines() ;
  1163.       drawnew() ;
  1164.    }
  1165. }
  1166. /*
  1167.  *   Advance the number by the delta, and check the boundaries.
  1168.  */
  1169. adv(o, d, n, w)
  1170. register short *o, *d, *n ;
  1171. short w ;
  1172. {
  1173.    *n = *o + *d ;
  1174.    if (*n < 0) {
  1175.       *n = 0 ;
  1176.       *d = randm(6) + 1 ;
  1177.    } else if (*n >= w) {
  1178.       *n = w - 1 ;
  1179.       *d = - randm(6) - 1 ;
  1180.    }
  1181. }
  1182. /*
  1183.  *   Advance the two points which make up the lines.
  1184.  */
  1185. advancelines() {
  1186.    register int i ;
  1187.  
  1188.    for (i=0; i<maxpoints; i++) {
  1189.       adv(ox+i, dx+i, nx+i, screenwidth) ;
  1190.       adv(oy+i, dy+i, ny+i, screenheight) ;
  1191.    }
  1192. }
  1193. /*
  1194.  *   Draw a new set of lines.
  1195.  */
  1196. drawnew() {
  1197.    register int i ;
  1198.    register short oldpen ;
  1199.    register struct box *bptr ;
  1200.  
  1201.    while (numlines >= maxlines) {
  1202.       oldpen = rastport->FgPen ;
  1203.       oldcol = 0xb0a ;
  1204.       SetAPen(rastport, 0L) ;
  1205.       bptr = eptr ;
  1206.       drawfunc(bptr) ;
  1207.       oldcol = 0xbfa ;
  1208.       SetAPen(rastport, (long)oldpen) ;
  1209.       numlines-- ;
  1210.       bptr++ ;
  1211.       if (bptr == store + MAXLINES)
  1212.          bptr = store ;
  1213.       eptr = bptr ;
  1214.    }
  1215.    bptr = ptr ;
  1216.    for (i=0; i<maxpoints; i++) {
  1217.       bptr->x[i] = ox[i] = nx[i] ;
  1218.       bptr->y[i] = oy[i] = ny[i] ;
  1219.    }
  1220.    drawfunc(bptr) ;
  1221.    numlines++ ;
  1222.    bptr++ ;
  1223.    if (bptr == store + MAXLINES) {
  1224.       bptr = store ;
  1225.       if (mdelta == 1) {
  1226.          maxlines++ ;
  1227.          if (maxlines >= MAXLINES - 1)
  1228.             mdelta = -1 ;
  1229.       } else {
  1230.          maxlines-- ;
  1231.          if (maxlines <= 2)
  1232.             mdelta = 1 ;
  1233.       }
  1234.    }
  1235.    ptr = bptr ;
  1236. }
  1237. /*
  1238.  *   This routine mucks with the colors.
  1239.  */
  1240. colors() {
  1241.    or = nr ;
  1242.    og = ng ;
  1243.    ob = nb ;
  1244.    adv(&or, &dr, &nr, 128) ;
  1245.    adv(&og, &dg, &ng, 128) ;
  1246.    adv(&ob, &db, &nb, 128) ;
  1247.    SetRGB4(&(globalblankscreen->ViewPort), 1L, (long)(nr >> 3),
  1248.                                     (long)(ng >> 3), (long)(nb >> 3)) ;
  1249. }
  1250. #define settime() {oldtime=0;}
  1251. #define gettime() (oldtime)
  1252. /*
  1253.  *   Our actual task, in an infinite loop.
  1254.  */
  1255. void taskrout() {
  1256.    register struct Task *task ;
  1257.  
  1258.    geta4() ;
  1259.    settime() ;
  1260.    makefunc() ;
  1261.    task = FindTask(0L) ;
  1262.    startlines() ;
  1263.    colors() ;
  1264.    while (SetSignal(0L, 0L)==0) {
  1265.       if (task->tc_Node.ln_Pri == 10)
  1266.          SetTaskPri(task, -20L) ;
  1267.       advancelines() ;
  1268.       drawnew() ;
  1269.       advancelines() ;
  1270.       drawnew() ;
  1271.       if (task->tc_Node.ln_Pri == 10)
  1272.          SetTaskPri(task, -20L) ;
  1273.       advancelines() ;
  1274.       drawnew() ;
  1275.       advancelines() ;
  1276.       drawnew() ;
  1277.       if (task->tc_Node.ln_Pri == 10)
  1278.          SetTaskPri(task, -20L) ;
  1279.       advancelines() ;
  1280.       drawnew() ;
  1281.       advancelines() ;
  1282.       drawnew() ;
  1283.       colors() ;
  1284.       if (gettime() >= 60) {
  1285.          settime() ;
  1286.          makefunc() ;
  1287.          SetRast(rastport, 0L) ;
  1288.          startlines() ;
  1289.       }
  1290.    }
  1291. done:
  1292.    Signal(globalbuddy, 1L << globalreplysignum) ;
  1293.    Wait(0L) ;
  1294. }
  1295. static int nevercli ;
  1296. #ifdef HELPKEY
  1297. /*
  1298.  *   Now we do hotkey magic to activate windows, bring them to front,
  1299.  *   etc.
  1300.  *
  1301.  *   Now we have a key, so we have to find a process with that name and
  1302.  *   bring her to front.  For now, we just deal with tasks, since the
  1303.  *   CLI stuff is so complicated.
  1304.  */
  1305. #define MAXMATCH (20)
  1306. char simplematch[3] = { ' ', '*', 0 } ;
  1307. struct Window *matchwindows[MAXMATCH] ;
  1308. extern long LockIBase() ;
  1309. windowtofront(key, qual)
  1310. char key ;
  1311. {
  1312.    long foo ;
  1313.    register int i, j ;
  1314.    int n ;
  1315.    register struct Window *w ;
  1316.    struct Screen *s ;
  1317.    struct Process *p ;
  1318.    struct MsgPort **mp ;
  1319.    struct CommandLineInterface *CLI ;
  1320.    int cli ;
  1321.    char *nameptr, *matchptr ;
  1322.    extern struct DosLibrary *DOSBase ;
  1323.    register struct hotkey *hk ;
  1324.    int shift, ctrl ;
  1325.    struct Window *activewindow ;
  1326.  
  1327. /*
  1328.  *   First we look for a matching record.
  1329.  */
  1330.    if (key == '.')
  1331.       goto goner ;
  1332.    shift = ((qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0) ;
  1333.    ctrl = ((qual & IEQUALIFIER_CONTROL) != 0) ;
  1334.    activewindow = NULL ;
  1335.    for (hk=hotkeys; hk; hk=hk->next)
  1336.       if (hk->key == key && 
  1337.           (hk->flags & SHIFT) == shift)
  1338.          break ;
  1339.    cli = 0 ;
  1340.    if (hk && hk->matchstring)
  1341.       matchptr = hk->matchstring ;
  1342.    else {
  1343.       matchptr = simplematch ;
  1344.       if (key == ' ')
  1345.          matchptr++ ;
  1346.       else if ('A' <= key && key <= 'Z')
  1347.          simplematch[0] = key ;
  1348.       else if ('0' <= key && key <= '9') {
  1349.          cli = key ;
  1350.          if (cli == '0')
  1351.             cli += 10 ;
  1352.          matchptr++ ;
  1353.       } else
  1354.          goto goner ;
  1355.    }
  1356.    n = 0 ;
  1357.    foo = LockIBase(0L) ;
  1358.    if (! ctrl && !(hk && (hk->flags & NOTINTUITION)) && !cli) {
  1359.       for (s=IntuitionBase->FirstScreen; s; s=s->NextScreen)
  1360.          for (w=s->FirstWindow; w; w=w->NextWindow) {
  1361.             if (w->UserPort) {
  1362.                p = (struct Process *)(w->UserPort->mp_SigTask) ;
  1363.                if (((struct Task *)p)->tc_Node.ln_Type == NT_PROCESS) {
  1364.                   if (p->pr_CLI) {
  1365.                      CLI = (struct CommandLineInterface *)BSTRtoS(p->pr_CLI) ;
  1366.                      if (bstrcmp(BSTRtoS((CLI)->cli_CommandName), matchptr) &&
  1367.                          n < MAXMATCH) {
  1368.                            if (w==IntuitionBase->ActiveWindow)
  1369.                               activewindow = w ;
  1370.                            matchwindows[n++] = w ;
  1371.                         }
  1372.                   } else {
  1373.                      if (sstrcmp(((struct Task *)p)->tc_Node.ln_Name, matchptr)
  1374.                           && n < MAXMATCH) {
  1375.                         if (w==IntuitionBase->ActiveWindow)
  1376.                            activewindow = w ;
  1377.                         matchwindows[n++] = w ;
  1378.                      }
  1379.                   }
  1380.                }
  1381.             }
  1382.          }
  1383.    }
  1384. /*
  1385.  *   Folks, there are still several/many windows of vulnerability
  1386.  *   here; I'll have to plug them.  For instance, what happens if a
  1387.  *   CLI goes away while we are doing this?  Or what happens if a
  1388.  *   window goes away later, when we are looking at IntuitionBase?
  1389.  */
  1390.    if (! ctrl && !(hk && (hk->flags & NOTCLI))) {
  1391.       mp = (struct MsgPort **)BSTRtoS(*(DOSBase->dl_Root)) ;
  1392.       for (j=1; j<(long)(mp[0]); j++)
  1393.          if (j != nevercli && mp[j] && (cli == 0 || j == cli - '0')) {
  1394.             p = (struct Process *)(mp[j]->mp_SigTask) ;
  1395.             CLI = (struct CommandLineInterface *)BSTRtoS(p->pr_CLI) ;
  1396.             if (!CLI->cli_Background &&
  1397.                   bstrcmp(BSTRtoS((CLI)->cli_CommandName), matchptr)) {
  1398.                infoptr->id_VolumeNode = NULL ;
  1399.                dos_packet(p->pr_ConsoleTask, ACTION_DISK_INFO,
  1400.                          ((long)(infoptr)) >> 2, 0L, 0L, 0L, 0L, 0L, 0L) ;
  1401.                if (w=(struct Window *)infoptr->id_VolumeNode)
  1402.                   if (n < MAXMATCH) {
  1403.                      if (w==IntuitionBase->ActiveWindow)
  1404.                         activewindow = w ;
  1405.                      matchwindows[n++] = w ;
  1406.                   }
  1407.             }
  1408.          }
  1409.    }
  1410.    if (shift)
  1411.       key += 100 ;
  1412.    if (ctrl || n==0) {
  1413.       UnlockIBase(foo) ;
  1414.       if (hk == NULL || hk->startstring == NULL)
  1415.          goto goner ;
  1416.       prito(0) ;
  1417.       Execute(hk->startstring, 0L, 0L) ;
  1418.       prito(20) ;
  1419.    } else {
  1420.       if (n == 1) {
  1421.          w = matchwindows[0] ;
  1422.       } else {
  1423. /*
  1424.  *   This is some real neat code.  We want to find the next window,
  1425.  *   that is, the window with the least address greater than the
  1426.  *   currently active window, unless the currently active window
  1427.  *   has the highest address, in which case we want to find the
  1428.  *   window with the least address.  Why this works is left as a
  1429.  *   puzzle for the reader.
  1430.  */
  1431.          if (activewindow) {
  1432.             w = activewindow ;
  1433.             for (j=0; j<n; j++)
  1434.                if ((w > activewindow) ^
  1435.                    (w > matchwindows[j]) ^
  1436.                    (matchwindows[j] > activewindow))
  1437.                   w = matchwindows[j] ;
  1438.          } else {
  1439.             w = NULL ;
  1440.             for (j=0; j<n; j++)
  1441.                if (lastwindows[key]==matchwindows[j]) {
  1442.                   w = lastwindows[key] ;
  1443.                   break ;
  1444.                }
  1445.             if (w==NULL)
  1446.                w = matchwindows[0] ;
  1447.          }
  1448.       }
  1449.       lastwindows[key] = w ;
  1450.       s = w->WScreen ;
  1451.       UnlockIBase(foo) ;
  1452.       ScreenToFront(s) ;
  1453. /*
  1454.  *   If only one window on screen, don't bring it to front
  1455.  *   (mostly for DPaint, but for other progs as well.)
  1456.  *   (Anyone know an easy way to see if this window is fully
  1457.  *   exposed?)
  1458.  */
  1459.       if (s->FirstWindow != w || w->NextWindow)
  1460.          WindowToFront(w) ;
  1461.       ActivateWindow(w) ;
  1462.    }
  1463.    return ;
  1464. goner:
  1465.    DisplayBeep(0L) ;
  1466. }
  1467. #endif
  1468. /*
  1469.  *   These two functions compare a given string `s' with a `key' string.
  1470.  *   The key string should be all upper case; this is a case insensitive
  1471.  *   match.  If the key string contains `*', this character is assumed to
  1472.  *   match the rest of the string (and it can only come at the end.)  We
  1473.  *   have a routine for BSTR's, and a routine for regular strings.
  1474.  */
  1475. int sstrcmp(s, key)
  1476. register char *s, *key ;
  1477. {
  1478.    while (1) {
  1479.       if (*key == '*')
  1480.          return(1) ;
  1481.       if (*key == 0)
  1482.          return(*s == 0) ;
  1483.       if (*s == 0)
  1484.          return(0) ;
  1485.       if (*s != *key &&
  1486.           (*s != *key + 32 || *s < 'a' || *s > 'z'))
  1487.          return(0) ;
  1488.       s++ ;
  1489.       key++ ;
  1490.    }
  1491. }
  1492. /*
  1493.  *   This is the same as above, only instead of using a null to
  1494.  *   end the string, we keep track of the number of characters.
  1495.  */
  1496. int bstrcmp(s, key)
  1497. register char *s, *key ;
  1498. {
  1499.    register int n ;
  1500.    register char *p ;
  1501.    register int nn ;
  1502.  
  1503.    n = *(unsigned char *)s++ ;
  1504.    nn = n ;
  1505.    for (p=s; *p > ' ' && nn > 0; p++, nn--)
  1506.       if (*p == '/' || *p == ':') {
  1507.          s = p + 1 ;
  1508.          n = nn - 1 ;
  1509.       }
  1510.    while (1) {
  1511.       if (*key == '*')
  1512.          return(1) ;
  1513.       if (*key == 0)
  1514.          return(n == 0) ;
  1515.       if (n == 0)
  1516.          return(0) ;
  1517.       if (*s != *key &&
  1518.           (*s != *key + 32 || *s < 'a' || *s > 'z'))
  1519.          return(0) ;
  1520.       s++ ;
  1521.       key++ ;
  1522.       n-- ;
  1523.    }
  1524. }
  1525. /*
  1526.  *   A place to hold an input line.
  1527.  */
  1528. #define MAXSTARTUPLINE (100)
  1529. char startbuf[MAXSTARTUPLINE] ;
  1530. char upline[MAXSTARTUPLINE] ;
  1531. /*
  1532.  *   Is a legit separator of some sort.
  1533.  */
  1534. int issep(s)
  1535. register char s ;
  1536. {
  1537.    return (s <= ' ' || s == '=' || s == ':' || s == ',' || s == '-') ;
  1538. }
  1539. /*
  1540.  *   Go to next `word' in the startup file.
  1541.  */
  1542. char *getword(s)
  1543. register char *s ;
  1544. {
  1545.    while (*s && issep(*s))
  1546.       s++ ;
  1547.    return(s) ;
  1548. }
  1549. int getint(s)
  1550. register char *s ;
  1551. {
  1552.    register int t = 0 ;
  1553.  
  1554.    while (*s <= ' ' && *s)
  1555.       s++ ;
  1556.    while ('0' <= *s && *s <= '9')
  1557.       t = t * 10 + *s++ - '0' ;
  1558.    return(t) ;
  1559. }
  1560. /*
  1561.  *   Upper case a string.
  1562.  */
  1563. char *upcase(dest, s)
  1564. char *dest ;
  1565. register char *s ;
  1566. {
  1567.    register char *d = dest ;
  1568.  
  1569.    while (*s) {
  1570.       if ('a' <= *s && *s <= 'z')
  1571.          *d++ = *s++ - 32 ;
  1572.       else
  1573.          *d++ = *s++ ;
  1574.    }
  1575.    *d = 0 ;
  1576.    return(dest) ;
  1577. }
  1578. /*
  1579.  *   Say we got a bad line.
  1580.  */
  1581. badline() {
  1582.    puts("Error in startup file!") ;
  1583.    puts(startbuf) ;
  1584. }
  1585. /*
  1586.  *   Copies a string from one place to another; string delimited by
  1587.  *   double quotes.
  1588.  */
  1589. char *cpystr(dest, src)
  1590. register char *dest, *src ;
  1591. {
  1592.    if (*src != '"')
  1593.       badline() ;
  1594.    else {
  1595.       src++ ;
  1596.       while (*src != '"' && *src != 0) {
  1597.          if (*src == '\\' && src[1] != 0)
  1598.             src++ ;
  1599.          *dest++ = *src++ ;
  1600.       }
  1601.       if (*src)
  1602.          src++ ;
  1603.    }
  1604.    *dest = 0 ;
  1605.    return(getword(src)) ;
  1606. }
  1607. /*
  1608.  *   Handle a single startup line that's not a comment and non-empty
  1609.  *   and been converted to all upper case.
  1610.  */
  1611. parseline(s, msg)
  1612. register char *s ;
  1613. struct OURMSG *msg ;
  1614. {
  1615.    int flags ;
  1616.    register short t ;
  1617.    register int key ;
  1618.    char *p ;
  1619.    register struct hotkey *hk ;
  1620.  
  1621.    flags = 0 ;
  1622.    if (strncmp(s, "COMMAND", 7)==0) {
  1623.       s = getword(s+7) ;
  1624.       cpystr(msg->cmd, s) ;
  1625.    } else if (strncmp(s, "TIMEOUT", 7)==0) {
  1626.       t = getint(s+7) ;
  1627.       if (t < 0)
  1628.          t = DEFTIME ;
  1629.       msg->interval = t ;
  1630.    } else if (strncmp(s, "LINES", 5)==0) {
  1631.       msg->draw = 1 ;
  1632.    } else if (strncmp(s, "NEVER", 5)==0) {
  1633.       nevercli = getint(s+5) ;
  1634.    } else if (strncmp(s, "BLANK", 5)==0) {
  1635.       msg->draw = -1 ;
  1636.    } else {
  1637.       if (strncmp(s, "SHIFT", 5)==0) {
  1638.          flags = SHIFT ;
  1639.          s = getword(s+5) ;
  1640.       }
  1641.       if (*s == 0)
  1642.          badline() ;
  1643.       else {
  1644.          if (issep(s[1]) &&
  1645.              (('A' <= *s && *s <= 'Z') ||
  1646.               ('0' <= *s && *s <= '9'))) {
  1647.             key = *s ;
  1648.             s = getword(s+1) ;
  1649.          } else if (strncmp(s, "SPACE", 5)==0) {
  1650.             key = ' ' ;
  1651.             s = getword(s+5) ;
  1652.          } else if (*s == 'F' && ('1' <= s[1] && s[1] <= '9')) {
  1653.             s++ ;
  1654.             t = *s++ - '0' ;
  1655.             if (t == 1 && *s == '0') {
  1656.                t = 10 ;
  1657.                s++ ;
  1658.             }
  1659.             key = t ;
  1660.             s = getword(s) ;
  1661.           } else {
  1662.             badline() ;
  1663.             return ;
  1664.          }
  1665.          if (strncmp(s, "INTUITION", 9)==0) {
  1666.             flags |= NOTCLI ;
  1667.             s = getword(s+9) ;
  1668.          } else if (strncmp(s, "CLI", 3)==0) {
  1669.             flags |= NOTINTUITION ;
  1670.             s = getword(s+3) ;
  1671.          }
  1672.          s = cpystr(upline, s) ;
  1673.          p = upline + strlen(upline) + 1 ;
  1674.          if (*s)
  1675.             cpystr(p, startbuf + (s-upline)) ;
  1676.          else
  1677.             *p = 0 ;
  1678.          t = sizeof(struct hotkey) + strlen(p) + strlen(upline) ;
  1679.          hk = AllocMem((long)t, MEMF_CLEAR | MEMF_PUBLIC) ;
  1680.          if (hk) {
  1681.             hk->key = key ;
  1682.             hk->flags = flags ;
  1683.             hk->next = hotkeys ;
  1684.         hk->structlen = t ;
  1685.         hk->matchstring = strcpy(hk->strings, upline) ;
  1686.         hk->startstring = strcpy(hk->strings + strlen(upline) + 1, p) ;
  1687.             if (hk->startstring[0]==0)
  1688.                hk->startstring = NULL ;
  1689.             hotkeys = hk ;
  1690.          } else
  1691.             puts("Out of memory in startup") ;
  1692.       }
  1693.    }
  1694. }
  1695. /*
  1696.  *   Handle the startup file.
  1697.  */
  1698. processstartup(s, msg)
  1699. char *s ;
  1700. struct OURMSG *msg ;
  1701. {
  1702.    FILE *f ;
  1703.    register char *p ;
  1704.  
  1705.    if (f=fopen(s, "r")) {
  1706.       while (fgets(startbuf, MAXSTARTUPLINE, f)) {
  1707.          p = getword(startbuf) ;
  1708.          if (*p != '*' && *p != '#' && *p != ';' && *p != 0) {
  1709.             upcase(upline, p) ;
  1710.             parseline(upline, msg) ;
  1711.          }
  1712.       }
  1713.       fclose(f) ;
  1714.    } else {
  1715.       puts("Couldn't open startup file:") ;
  1716.       puts(s) ;
  1717.    }
  1718. }
  1719. #ifdef HELPKEY
  1720. /*
  1721.  *   This stuff down here handles the raw key conversion stuff
  1722.  *   properly.  Thanks to Willy Langeveld and Carolyn Scheppner.
  1723.  */
  1724. char *dos_rkcv();
  1725. int  dos_rkcvinit(), dos_rkcvexit();
  1726. struct IOStdReq ConStdReq;
  1727. /*
  1728.  *   This code won't compile under Manx unless you delete the
  1729.  *   `ConsoleDevice' function in functions.h, or perform a kludge
  1730.  *   like the one I did when I included it.  Why the hell does
  1731.  *   Manx have that in there?  If you try to use it, it comes out
  1732.  *   undefined, but if you rename the following, it won't link
  1733.  *   because it needs the function `ConsoleDevice'.
  1734.  */
  1735. long ConsoleDevice ;
  1736. /**
  1737. *
  1738. *  Calling sequence:
  1739. *  =================
  1740. *
  1741. *    result = (char *) dos_rkcv(code, buffer, length);
  1742. *
  1743. *  Description:
  1744. *  ============
  1745. *
  1746. *    Covert raw key number to array of console device ascii text
  1747. *    using the default keymap.
  1748. *
  1749. *  Inputs:
  1750. *  =======
  1751. *
  1752. *    int code        Raw key number.
  1753. *    int qual        Qualifier.
  1754. *    char *buffer        Pointer to an array of char to receive the
  1755. *                conversion.
  1756. *    int length        length of buffer.
  1757. *
  1758. *  Outputs:
  1759. *  ========
  1760. *
  1761. *    F. value:        NULL on conversion failure, or pointer to
  1762. *                buffer on success.
  1763. *
  1764. **/
  1765. char *dos_rkcv(code, qual, buffer, length)
  1766. int code;
  1767. int qual;
  1768. char *buffer;
  1769. int length;
  1770. {
  1771.    static struct InputEvent event;
  1772.  
  1773.    event.ie_Class = IECLASS_RAWKEY;
  1774.    event.ie_Code = code;
  1775.    event.ie_Qualifier = qual;
  1776.  
  1777.    if (RawKeyConvert(&event, buffer, (long) length, NULL) == 0L) return(0L);
  1778.  
  1779.    return(buffer);
  1780. }
  1781.  
  1782. /**
  1783. *
  1784. *  Calling sequence:
  1785. *  =================
  1786. *
  1787. *    error = dos_rkcvinit();
  1788. *
  1789. *  Description:
  1790. *  ============
  1791. *
  1792. *    Open the Console device for later use with dos_rkcv().
  1793. *
  1794. *  Inputs:
  1795. *  =======
  1796. *
  1797. *    None
  1798. *
  1799. *  Outputs:
  1800. *  ========
  1801. *
  1802. *    F. value:        1 on failure, zero otherwise.
  1803. *                
  1804. *
  1805. **/
  1806. int dos_rkcvinit()
  1807. {
  1808.    if (OpenDevice("console.device", -1L, &ConStdReq, 0L) != NULL) {
  1809.       ConsoleDevice = 0L;
  1810.       return(1);
  1811.    }
  1812.    else {
  1813.       ConsoleDevice = (long) ConStdReq.io_Device;
  1814.       return(0);
  1815.    }
  1816. }
  1817.  
  1818. /**
  1819. *
  1820. *  Calling sequence:
  1821. *  =================
  1822. *
  1823. *    error = dos_rkcvexit();
  1824. *
  1825. *  Description:
  1826. *  ============
  1827. *
  1828. *    Close the Console device after use with dos_rkcv().
  1829. *
  1830. *  Inputs:
  1831. *  =======
  1832. *
  1833. *    None
  1834. *
  1835. *  Outputs:
  1836. *  ========
  1837. *
  1838. *    F. value:        Always zero;
  1839. *                
  1840. **/
  1841. int dos_rkcvexit()
  1842. {
  1843.    if (ConsoleDevice) CloseDevice(&ConStdReq);
  1844.    return(0);
  1845. }
  1846. /*
  1847.  *   Set up the key conversion table.  Note that the buffer has to be
  1848.  *   long word aligned!
  1849.  */
  1850. initkeytoasc() {
  1851.    register int i ;
  1852.    char buf[100] ;
  1853.  
  1854.    for (i=0; i<128; i++)
  1855.       keytoasc[i] = '.' ;
  1856.    if (dos_rkcvinit())
  1857.       return(1) ;
  1858.    for (i=0; i<128; i++) {
  1859.       buf[1] = 0 ;
  1860.       if (dos_rkcv(i, 0, buf, 100) && buf[1] == 0 &&
  1861.           (buf[0] == ' ' ||
  1862.            ('a' <= buf[0] && buf[0] <= 'z' && (buf[0] -= 32)) ||
  1863.            ('0' <= buf[0] && buf[0] <= '9'))) {
  1864.          keytoasc[i] = buf[0] ;
  1865.       }
  1866.    }
  1867. /*
  1868.  *   Have to handle the function keys separately
  1869.  */
  1870.    for (i=80; i<90; i++)
  1871.       keytoasc[i] = i-79 ;
  1872.    dos_rkcvexit() ;
  1873.    return(0) ;
  1874. }
  1875. #endif
  1876. /*
  1877.  *   Save a byte or two.
  1878.  */
  1879. _wb_parse() {}
  1880.